package com.gjy.design.prototype;


import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author gjy
 * @version 1.0
 * @since 2025-11-11 09:36:20
 */
public class Person implements Serializable, Cloneable {
    private static final long serialVersionUID = -871787455477786767L;

    private String name;
    private int age;
    private Address address;   // 可变引用字段

    public Person(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    // ----------------------- 1) Object.clone() 示例（浅拷贝） -----------------------
    // 手动实现深拷贝
    @Override
    public Person clone() {
        try {
            // 先做浅拷贝
            Person cloned = (Person) super.clone();
            // 再对可变引用字段进行深拷贝
            cloned.address = new Address(this.address);
            return cloned;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // 不会发生
        }
    }

    // ----------------------- 2) 拷贝构造器示例（深拷贝） -----------------------
    public Person(Person other) {
        this.name = other.name;
        this.age = other.age;
        // 递归拷贝可变子对象
        this.address = new Address(other.address);
    }

    // ----------------------- 3) 序列化克隆（深拷贝） -----------------------
    // 需要实现Serializable (Person 已经实现)
    public Person deepCopyViaSerialization() {
        // JDK 8 没有内置的序列化克隆工具，这里演示手写
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(this);
            oos.flush();

            try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                 ObjectInputStream ois = new ObjectInputStream(bais)) {
                return (Person) ois.readObject();
            }
        } catch (Exception e) {
            throw new RuntimeException("Deep copy via serialization failed", e);
        }
    }

    // ----------------------- 4) Supplier（函数式）-----------------------
    public static Person createPrototype() {
        return new Person("Alice", 30, new Address("Main St", 123));
    }

    // ----------------------- 5) 原型注册表 -----------------------
    public static class PrototypeRegistry {
        private final Map<String, Person> prototypes = new HashMap<>();

        public void addPrototype(String key, Person prototype) {
            prototypes.put(key, prototype);
        }

        public Person getPrototype(String key) {
            Person p = prototypes.get(key);
            if (p == null) {
                throw new IllegalArgumentException("No prototype for key: " + key);
            }
            // 这里演示两种克隆方式：拷贝构造器 or 序列化
            return p.clone(); // 或者使用 p.deepCopyViaSerialization()
        }
    }

    // Getters / Setters / toString
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", address=" + address + '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name) &&
                Objects.equals(address, person.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, address);
    }

}
